package bsk_dac.actions;

import bsk_dac.DACPanel;
import bsk_dac.MainDACFrame;
import bsk_dac.PrivilegesMode;
import bsk_dac.PrivilegesPanel;
import bsk_dac.UserPanel;
import bsk_dac.accesscontrol.TableAccess;
import bsk_dac.accesscontrol.AccessType;
import bsk_dac.database.DatabaseFacade;
import bsk_dac.users.IUsersManager;
import bsk_dac.users.User;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JCheckBox;
import javax.swing.JOptionPane;

/**
 * Klasa służy do zarządzania przekazywaniem uprawnień
 */
public class SelectingPrivileges implements ActionListener {

    private JCheckBox checkBox;
    private DACPanel dacPanel;
    private IUsersManager usersManager;
    private PrivilegesPanel privilegesPanel;
    private User privilegesPanelUser;
    private User selectedUser;
    private String tableName;
    private TableAccess changedAccess;

    public SelectingPrivileges(DACPanel dacPanel) {
        this.dacPanel = dacPanel;
    }

    public void changeAccessGiveModeInDatabase(String tableName, String acc, String username, boolean permission, boolean givePermission) throws SQLException {
        int user_id = DatabaseFacade.getUserId(username);
        int table_id = DatabaseFacade.getTableId(tableName);

        if (DatabaseFacade.isPermissionsInDatabase(user_id, table_id, acc)) {
            DatabaseFacade.setTablePriveleges(user_id, table_id, acc, permission, givePermission);
        } else {
            DatabaseFacade.insertNewPermission(user_id, table_id, acc, permission, givePermission);
        }


        //Dodanie do histori jeśli przekazujemy komuś prawa
        if (permission == true && MainDACFrame.adminMode == false) {
            int user_give_id = DatabaseFacade.getUserId(selectedUser.getUserName());
            int user_get_id = user_id;
            int tp_id = DatabaseFacade.getTablePrivelegesId(user_get_id, table_id, acc);
            DatabaseFacade.addToHistory(user_get_id, user_give_id, tp_id, acc, table_id);
            System.out.println("Zapisanie do histori przekazania '" + acc + "' do '" + DatabaseFacade.getTableName(table_id) + "' przez '" + DatabaseFacade.getUserName(user_give_id) + "' dla '" + DatabaseFacade.getUserName(user_get_id) + "'");
        }
    }

    public void actionPerformed(ActionEvent e) {

        usersManager = MainDACFrame.getUsersManager();
        checkBox = (JCheckBox) e.getSource();
        privilegesPanel = (PrivilegesPanel) checkBox.getParent();
        privilegesPanelUser = privilegesPanel.getUser();
        selectedUser = usersManager.getSelectedUser();
        tableName = privilegesPanel.getTableName();
        changedAccess = privilegesPanelUser.getTableAccess(tableName);

        try {
            if (usersManager.getSelectedUser() != privilegesPanelUser
                    && usersManager.getSelectedUser() != null
                    && checkBox.isEnabled()) {
                userGivePermissionsAction();
            } else {
                if (MainDACFrame.adminMode == true) {
                    adminGivePermissionsAction();
                }
            }
        } catch (SQLException ex) {
            Logger.getLogger(SelectingPrivileges.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void userGivePermissionsAction() throws SQLException {
        //Jeśli odznaczyliśmy komuś checkboxa
        if (checkBox.isSelected() == false) {
            //Wywołanie revoke
            System.out.println("Revoke ...");
            int table_id = DatabaseFacade.getTableId(tableName);
            int user_give_id = DatabaseFacade.getUserId(selectedUser.getUserName());
            int user_get_id = DatabaseFacade.getUserId(privilegesPanelUser.getUserName());

            if (privilegesPanel.getSelectCB() == checkBox) {
                revokePermission(table_id, "select", user_give_id, user_get_id);
            }
            if (privilegesPanel.getUpdateCB() == checkBox) {
                revokePermission(table_id, "update", user_give_id, user_get_id);
            }
            if (privilegesPanel.getDeleteCB() == checkBox) {
                revokePermission(table_id, "delete", user_give_id, user_get_id);
            }
            if (privilegesPanel.getInsertCB() == checkBox) {
                revokePermission(table_id, "insert", user_give_id, user_get_id);
            }

        } else {
            //Delegacja uprawnień lub przekazanie
            if (privilegesPanelUser.getUserAccess().getPrivilegesStatus(AccessType.GIVE_PRIV)) {
                if (JOptionPane.OK_OPTION == JOptionPane.showConfirmDialog(dacPanel,
                        "Czy chcesz oddać uprawnienia użytkownikowi \"" + privilegesPanelUser.getUserName() + "\" ?",
                        "Oddanie uprawnień", JOptionPane.YES_NO_OPTION)) {
                    //Oddanie uprawnień, jeśli użytkownik ma do tego prawo do przejmowania uprawnień
                    for (UserPanel userPanel : dacPanel.getUsersPanels()) {
                        if (userPanel.getUser().getUserName().equals(privilegesPanelUser.getUserName())) {
                            userPanel.givePermissions();
                        }
                    }
                } else {
                    checkBox.setEnabled(false);
                }
            } else {
                if (JOptionPane.OK_OPTION == JOptionPane.showConfirmDialog(dacPanel,
                        "Czy chcesz przekazać uprawnienie do przekazywania uprawnień użytkownikowi \"" + privilegesPanelUser.getUserName() + "\" ?",
                        "Przekazanie dodatkowego uprawnienia", JOptionPane.YES_NO_OPTION)) {
                    setPermissions(true, true);
                } else {
                    setPermissions(true, false);
                }
                //Jeśli przekazaliśmy prawa to wyłączamy checkboxa
                checkBox.setEnabled(false);
            }
        }
/*

        //Jeśli odznaczyliśmy komuś checkboxa
        if (checkBox.isSelected() == false) {
            //Wywołanie revoke
            System.out.println("Revoke ...");
            int table_id = DatabaseFacade.getTableId(tableName);
            int user_give_id = DatabaseFacade.getUserId(selectedUser.getUserName());
            int user_get_id = DatabaseFacade.getUserId(privilegesPanelUser.getUserName());

            if (privilegesPanel.getSelectCB() == checkBox) {
                revokePermission(table_id, "select", user_give_id, user_get_id);
            }
            if (privilegesPanel.getUpdateCB() == checkBox) {
                revokePermission(table_id, "update", user_give_id, user_get_id);
            }
            if (privilegesPanel.getDeleteCB() == checkBox) {
                revokePermission(table_id, "delete", user_give_id, user_get_id);
            }
            if (privilegesPanel.getInsertCB() == checkBox) {
                revokePermission(table_id, "insert", user_give_id, user_get_id);
            }

        } else {
            //Delegacja uprawnień lub przekazanie
            if (privilegesPanelUser.getUserAccess().getPrivilegesStatus(AccessType.GIVE_PRIV)) {
                //Oddanie uprawnień, jeśli użytkownik ma do tego prawo do przejmowania uprawnień
                for (UserPanel userPanel : dacPanel.getUsersPanels()) {
                    if (userPanel.getUser().getUserName().equals(privilegesPanelUser.getUserName())) {
                        userPanel.givePermissions();
                    }
                }
            } else {
                setPermissions(true, true);
                checkBox.setEnabled(false);
            }
        }*/
        dacPanel.refreshPanelsAccess();
    }

    private void revokePermission(int table_id, String permissionName, int user_give_id, int user_get_id) {
        try {
            System.out.println("Użytkownik " + DatabaseFacade.getUserName(user_give_id) + " zbiera prawa " + permissionName + " do " + tableName + " dane '" + DatabaseFacade.getUserName(user_get_id) + "'");
            int tp_id = DatabaseFacade.getTablePrivelegesId(user_give_id, table_id, permissionName);
            //Pobranie id histori w których rozdaliśmy dane uprawnienie
            ArrayList<Integer> historiesId = DatabaseFacade.getHistoryID(user_give_id, permissionName, table_id);
            //Zabranie użytkownikom uprawnienia
            int hisId = DatabaseFacade.getHistoryID(user_give_id, user_get_id, permissionName, table_id);
            System.out.println("Szukanie w histori " + hisId);
            int tpIdToRevoke = DatabaseFacade.getTablePermissionIdByHistory(hisId);
            //Zmiana uprawnień w bazie
            DatabaseFacade.removeAllPrivileges(tpIdToRevoke);

            //Zmiana uprawnień lokalnie
            String userGetName = DatabaseFacade.getUserName(user_get_id);
            User userGet = usersManager.getUser(userGetName);
            TableAccess userGetTableAccess = userGet.getTableAccess(tableName);

            if (permissionName.equals("select")) {
                userGetTableAccess.setPrivileges(AccessType.SELECT, false);
                userGetTableAccess.setUserGivePermission(AccessType.SELECT, false);
            }

            if (permissionName.equals("insert")) {
                userGetTableAccess.setPrivileges(AccessType.INSERT, false);
                userGetTableAccess.setUserGivePermission(AccessType.INSERT, false);
            }

            if (permissionName.equals("update")) {
                userGetTableAccess.setPrivileges(AccessType.UPDATE, false);
                userGetTableAccess.setUserGivePermission(AccessType.UPDATE, false);
            }

            if (permissionName.equals("delete")) {
                userGetTableAccess.setPrivileges(AccessType.DELETE, false);
                userGetTableAccess.setUserGivePermission(AccessType.DELETE, false);
            }

            revokePermission(table_id, permissionName, user_get_id);

            //Usunięcie histori
            DatabaseFacade.deleteHistories(historiesId);
        } catch (SQLException se) {
            se.printStackTrace();
        }
    }

    private void revokePermission(int table_id, String permissionName, int user_give_id) {
        try {
            System.out.println("Użytkownik " + DatabaseFacade.getUserName(user_give_id) + " zbiera prawa " + permissionName + " do " + tableName);
            int tp_id = DatabaseFacade.getTablePrivelegesId(user_give_id, table_id, permissionName);
            //Pobranie id histori w których rozdaliśmy dane uprawnienie
            ArrayList<Integer> historiesId = DatabaseFacade.getHistoryID(user_give_id, permissionName, table_id);
            //Zabranie użytkownikom uprawnienia
            for (int hisId : historiesId) {
                System.out.println("Szukanie w histori " + hisId);
                int tpIdToRevoke = DatabaseFacade.getTablePermissionIdByHistory(hisId);
                int user_get_id = DatabaseFacade.getHistoryUserGetId(hisId);
                //Zmiana uprawnień w bazie
                DatabaseFacade.removeAllPrivileges(tpIdToRevoke);

                //Zmiana uprawnień lokalnie
                String userGetName = DatabaseFacade.getUserName(user_get_id);
                User userGet = usersManager.getUser(userGetName);
                TableAccess userGetTableAccess = userGet.getTableAccess(tableName);

                if (permissionName.equals("select")) {
                    userGetTableAccess.setPrivileges(AccessType.SELECT, false);
                    userGetTableAccess.setUserGivePermission(AccessType.SELECT, false);
                }

                if (permissionName.equals("insert")) {
                    userGetTableAccess.setPrivileges(AccessType.INSERT, false);
                    userGetTableAccess.setUserGivePermission(AccessType.INSERT, false);
                }

                if (permissionName.equals("update")) {
                    userGetTableAccess.setPrivileges(AccessType.UPDATE, false);
                    userGetTableAccess.setUserGivePermission(AccessType.UPDATE, false);
                }

                if (permissionName.equals("delete")) {
                    userGetTableAccess.setPrivileges(AccessType.DELETE, false);
                    userGetTableAccess.setUserGivePermission(AccessType.DELETE, false);
                }

                revokePermission(table_id, permissionName, user_get_id);

            }

            //Usunięcie histori
            DatabaseFacade.deleteHistories(historiesId);
        } catch (SQLException se) {
            se.printStackTrace();
        }
    }

    private void adminGivePermissionsAction() throws SQLException {

        //Sprawdzenie czy odznaczyliśmy checkboxa
        if (checkBox.isSelected() == false && checkBox.getBackground() != Color.RED) {
            setPermissions(false, false);
            System.out.println(new Date() + " Admin: Zabranie praw użytkownikowi '" + privilegesPanelUser.getUserName() + "'");
        } else {
            if (checkBox.getBackground() == Color.RED) {
                setPermissions(true, true);
                checkBox.setBackground(Color.BLACK);
                checkBox.setSelected(true);
                System.out.println(new Date() + " Admin: Danie maksymalnych praw użytkownikowi '" + privilegesPanelUser.getUserName() + "'");
            } else {
                setPermissions(true, false);
                checkBox.setBackground(Color.RED);
                System.out.println(new Date() + " Admin: Danie prawa bez przekzaywania użytkownikowi '" + privilegesPanelUser.getUserName() + "'");
            }
        }
    }

    private void setPermissions(boolean permission, boolean givePermission) throws SQLException {
        if (privilegesPanel.getSelectCB() == checkBox) {
            changedAccess.setPrivileges(AccessType.SELECT, permission);
            changedAccess.setUserGivePermission(AccessType.SELECT, givePermission);
            changeAccessGiveModeInDatabase(tableName, AccessType.SELECT.name().toLowerCase(), privilegesPanelUser.getUserName(), permission, givePermission);
        }
        if (privilegesPanel.getUpdateCB() == checkBox) {
            changedAccess.setPrivileges(AccessType.UPDATE, permission);
            changedAccess.setUserGivePermission(AccessType.UPDATE, givePermission);
            changeAccessGiveModeInDatabase(tableName, AccessType.UPDATE.name().toLowerCase(), privilegesPanelUser.getUserName(), permission, givePermission);
        }
        if (privilegesPanel.getDeleteCB() == checkBox) {
            changedAccess.setPrivileges(AccessType.DELETE, permission);
            changedAccess.setUserGivePermission(AccessType.DELETE, givePermission);
            changeAccessGiveModeInDatabase(tableName, AccessType.DELETE.name().toLowerCase(), privilegesPanelUser.getUserName(), permission, givePermission);
        }
        if (privilegesPanel.getInsertCB() == checkBox) {
            changedAccess.setPrivileges(AccessType.INSERT, permission);
            changedAccess.setUserGivePermission(AccessType.INSERT, givePermission);
            changeAccessGiveModeInDatabase(tableName, AccessType.INSERT.name().toLowerCase(), privilegesPanelUser.getUserName(), permission, givePermission);
        }
    }
}
